/* -*- Mode: c; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/*
  RefObject (http://code.google.com/p/refobject/)
  Copyright (C) 2010-2011 MIURA Shirow (sharow)
*/

#include "RefObjectInternal.h"

struct RefObject_ {
    int mRefCount;
    RefObjectDestructor mDestructorProc;
    RefTypeObject **mTypeObject;
    void *mObject[1];           /* flexible array */
};

int
RefObject_SizeOf(void)
{
    return sizeof(RefObject);
}

void *
RefObject_Construct(RefObject *aRefObject, RefTypeObject **aTypeObject, RefObjectDestructor aDestructor)
{
    aRefObject->mRefCount = 1;
    aRefObject->mTypeObject = aTypeObject;
    aRefObject->mDestructorProc = aDestructor;
    return RefObject_GetObject(aRefObject);
}

void
RefObject_IncRef(RefObject *aRefObject)
{
    aRefObject->mRefCount += 1;
}

void
RefObject_XIncRef(RefObject *aRefObject)
{
    if (aRefObject) {
        aRefObject->mRefCount += 1;
    }
}

int
RefObject_DecRef(RefObject *aRefObject)
{
    aRefObject->mRefCount -= 1;
    if (aRefObject->mRefCount == 0) {
        if (aRefObject->mDestructorProc) {
            aRefObject->mDestructorProc(aRefObject);
        }
        return 1;               /* delete */
    } else {
        return 0;               /* active */
    }
}

int
RefObject_XDecRef(RefObject *aRefObject)
{
    if (aRefObject) {
        return RefObject_DecRef(aRefObject);
    }
    return 1;               /* delete */
}

void *
RefObject_GetObject(RefObject *aRefObject)
{
    return (void *)&aRefObject->mObject[0];
}

RefTypeObject **
RefObject_GetTypeObject(RefObject *aRefObject)
{
    return aRefObject->mTypeObject;
}
